﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using UtilZ.Dotnet.Ex.Base;
using UtilZ.Dotnet.Ex.ZLog;

namespace UtilZ.Dotnet.WindowsDesktopEx.Winform
{
    /// <summary>
    /// 8个圆圈旋转加载控件
    /// </summary>
    public class EllipseRotateLoadingControl : Control, ISupportInitialize
    {
        #region 属性
        private float _ellipseSize = 20f;
        /// <summary>
        /// 获取或设置旋转圆直径
        /// </summary>
        public float EllipseSize
        {
            get { return _ellipseSize; }
            set
            {
                if (value < 1)
                {
                    throw new ArgumentOutOfRangeException($"最大尺寸值不能小于最小尺寸值1,值{value}无效");
                }

                if (value > 1000)
                {
                    throw new ArgumentOutOfRangeException($"最大尺寸值不能大于1000,值{value}无效");
                }

                _ellipseSize = value;

                this.InitEllipseInfo();
                this.Draw();
            }
        }

        private bool _rotateDirection = true;
        /// <summary>
        /// 获取或设置旋转方向[true:顺时针;false:逆时针]
        /// </summary>
        public bool RotateDirection
        {
            get { return _rotateDirection; }
            set { _rotateDirection = value; }
        }



        private double _durationMilliseconds = 1200d;
        /// <summary>
        /// 获取或设置转一圈的时长,单位毫秒
        /// </summary>
        public double DurationMilliseconds
        {
            get { return _durationMilliseconds; }
            set
            {
                if (value < 1)
                {
                    throw new ArgumentOutOfRangeException($"转一圈的时长不能小于1,值{value}无效");
                }

                _durationMilliseconds = value;
            }
        }


        /// <summary>
        /// 获取或设置旋转刷新间隔
        /// </summary>
        public int Interval
        {
            get { return this._timer.Interval; }
            set
            {
                if (value < 0)
                {
                    throw new ArgumentOutOfRangeException($"动画间隔不能小于0,值:{value}无效");
                }

                this._timer.Interval = value;
            }
        }



        private Brush[] _fillBrushes = new Brush[]
        {
            Brushes.Gray,
            Brushes.Gray,
            Brushes.Gray,
            Brushes.Gray,
            Brushes.Gray,
            Brushes.Gray,
            Brushes.Gray,
            Brushes.Gray,
        };
        /// <summary>
        /// 获取或设置旋转圆填充笔刷
        /// </summary>
        public Brush[] FillBrushes
        {
            get { return _fillBrushes; }
            set
            {
                if (value == null)
                {
                    throw new ArgumentNullException();
                }

                _fillBrushes = value;

                this.InitEllipseInfo();
                this.Draw();
            }
        }

        private int _brushIndex = 0;
        private Brush GetBrush()
        {
            Brush[] fillBrushes = _fillBrushes;
            if (this._brushIndex >= fillBrushes.Length)
            {
                this._brushIndex = 0;
            }

            Brush brush = fillBrushes[this._brushIndex];
            this._brushIndex++;

            return brush;
        }
        #endregion


        #region ISupportInitialize
        /// <summary>
        /// 用信号通知对象初始化即将开始
        /// </summary>
        public void BeginInit()
        {
            
        }

        /// <summary>
        /// 用信号通知对象初始化已完成
        /// </summary>
        public void EndInit()
        {
            
        }
        #endregion


        /// <summary>
        /// 图形双缓冲缓冲区对象
        /// </summary>
        private BufferedGraphics _grafx = null;

        /// <summary>
        /// 8个圆圈
        /// </summary>
        private EllipseInfoCollection _ellipseInfos = null;

        /// <summary>
        /// 动画更新定时器
        /// </summary>
        private readonly Timer _timer;
        private double _angle = 0d;

        private readonly Stopwatch _drawStopwatch = new Stopwatch();


        /// <summary>
        /// 构造函数初始化
        /// </summary>
        public EllipseRotateLoadingControl()
            : base()
        {
            //设置绘制样式
            //ControlStyles styles = ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint |
            //    ControlStyles.Opaque | ControlStyles.OptimizedDoubleBuffer | ControlStyles.SupportsTransparentBackColor |
            //    ControlStyles.ResizeRedraw;
            //ControlStyles styles = ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint |
            //    ControlStyles.Opaque | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.SupportsTransparentBackColor;
            //this.SetStyle(styles, true);

            this.SetStyle(ControlStyles.UserPaint, true);
            this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
            this.SetStyle(ControlStyles.ResizeRedraw, true);

            this.DoubleBuffered = true;
            base.BackColor = Color.Transparent;

            //大小
            this.Size = new System.Drawing.Size(54, 54);
            //最小大小
            this.MinimumSize = this.Size;

            this._timer = new Timer();
            this._timer.Interval = 1;
            this._timer.Tick += _timer_Tick;
        }


        private void _timer_Tick(object sender, EventArgs e)
        {
            this.Draw();
        }

        /// <summary>
        /// 启动动画
        /// </summary>
        public void StartAnimal()
        {
            this._drawStopwatch.Start();
            this._timer.Start();
        }

        /// <summary>
        /// 停止动画
        /// </summary>
        public void StopAnimal()
        {
            this._drawStopwatch.Stop();
            this._timer.Stop();
        }




        /// <summary>
        /// 重写OnSizeChanged
        /// </summary>
        /// <param name="e"></param>
        protected override void OnSizeChanged(EventArgs e)
        {
            try
            {
                //重新创建双缓冲
                this.CreateBufferedGraphics();
                this.InitEllipseInfo();
                this.Draw();
                base.OnSizeChanged(e);
            }
            catch (Exception ex)
            {
                ZLoger.Error(ex);
            }
        }

        /// <summary>
        /// 创建双缓冲绘图
        /// </summary>
        private void CreateBufferedGraphics()
        {
            // Sets the maximum size for the primary graphics buffer
            // of the buffered graphics context for the application
            // domain.  Any allocation requests for a buffer larger 
            // than this will create a temporary buffered graphics 
            // context to host the graphics buffer.
            BufferedGraphicsManager.Current.MaximumBuffer = new Size(this.Width + 1, this.Height + 1);
            BufferedGraphics grafx = null;
            //当宽度或高度为0时,缓冲区创建会报系统异常
            if (this.Width != 0 && this.Height != 0)
            {
                // Allocates a graphics buffer the size of this form
                // using the pixel format of the Graphics created by 
                // the Form.CreateGraphics() method, which returns a 
                // Graphics object that matches the pixel format of the form.
                //BufferedGraphics grafx = BufferedGraphicsManager.Current.Allocate(this.CreateGraphics(), new Rectangle(0, 0, this.Width, this.Height));
                grafx = BufferedGraphicsManager.Current.Allocate(Graphics.FromHwnd(this.Handle), new Rectangle(0, 0, this.Width, this.Height));
                grafx.Graphics.SmoothingMode = SmoothingMode.HighQuality;
                grafx.Graphics.PixelOffsetMode = PixelOffsetMode.HighSpeed;
            }

            if (this._grafx != null)
            {
                this._grafx.Graphics.Dispose();
                this._grafx.Dispose();
            }

            this._grafx = grafx;
        }

        private void InitEllipseInfo()
        {
            if (this._ellipseInfos != null)
            {
                this._ellipseInfos.ForEach(t => { t.Dispose(); });
            }


            Rectangle clientRectangle = this.ClientRectangle;
            float xOffset, yOffset, areaSize;
            if (clientRectangle.Width > clientRectangle.Height)
            {
                areaSize = clientRectangle.Height;
                xOffset = (clientRectangle.Width - clientRectangle.Height) / 2;
                yOffset = 0f;
            }
            else
            {
                areaSize = this.ClientRectangle.Width;
                xOffset = 0f;
                yOffset = (clientRectangle.Height - clientRectangle.Width) / 2;
            }

            this._angle = 0d;
            const int ANIMAL_ELLIPSE_COUNT = 8;//动画圆个数
            float rotatePathR = areaSize / 2;//旋转路径圆半径
            float animalR = this._ellipseSize / 2;//动画圆半径
            float animalEllipseCenterAxisOffset = rotatePathR - (float)(Math.Sqrt(2) / 2 * (Math.Sqrt(Math.Pow(animalR, 2) * 2) + rotatePathR - animalR));//动画圆圆心坐标偏移量
            var ellipseInfos = new EllipseInfoCollection(new PointF(clientRectangle.Width / 2, clientRectangle.Height / 2), rotatePathR, animalR, ANIMAL_ELLIPSE_COUNT);
            float x, y;
            Brush fill;
            this._brushIndex = 0;

            for (int i = 0; i < ANIMAL_ELLIPSE_COUNT; i++)
            {
                switch (i)
                {
                    case 0:
                        x = 0f;
                        y = rotatePathR - animalR;
                        break;
                    case 1:
                        x = animalEllipseCenterAxisOffset;
                        y = animalEllipseCenterAxisOffset;
                        break;
                    case 2:
                        x = rotatePathR - animalR;
                        y = 0f;
                        break;
                    case 3:
                        x = areaSize - animalEllipseCenterAxisOffset - this._ellipseSize;
                        y = animalEllipseCenterAxisOffset;
                        break;
                    case 4:
                        x = areaSize - this._ellipseSize;
                        y = rotatePathR - animalR;
                        break;
                    case 5:
                        x = areaSize - animalEllipseCenterAxisOffset - this._ellipseSize;
                        y = x;
                        break;
                    case 6:
                        x = rotatePathR - animalR;
                        y = areaSize - this._ellipseSize;
                        break;
                    case 7:
                        x = animalEllipseCenterAxisOffset;
                        y = areaSize - animalEllipseCenterAxisOffset - this._ellipseSize;
                        break;
                    default:
                        throw new Exception($"未实现的点索引{i}");
                }

                x += xOffset;
                y += yOffset;

                fill = GetBrush();
                ellipseInfos.Add(new EllipseInfo(new PointF(x, y), fill, i));
            }

            this._ellipseInfos = ellipseInfos;
        }





        /// <summary>
        /// 重写OnPaint
        /// </summary>
        /// <param name="e"></param>
        protected override void OnPaint(PaintEventArgs e)
        {
            try
            {
                this._grafx.Render(e.Graphics);
            }
            catch (Exception ex)
            {
                ZLoger.Error(ex);
            }
        }

        /// <summary>
        /// 重写OnPaintBackground
        /// </summary>
        /// <param name="pevent"></param>
        protected override void OnPaintBackground(PaintEventArgs pevent)
        {
            //配合构造函数中this.DoubleBuffered = true;解决闪屏问题
            return;
        }



        private void Draw()
        {
            try
            {
                var grafx = this._grafx;
                if (grafx == null)
                {
                    return;
                }

                //全部绘制
                Graphics graphics = grafx.Graphics;
                graphics.Clear(this.BackColor);

                EllipseInfoCollection ellipseInfos = this._ellipseInfos;
                if (ellipseInfos == null)
                {
                    return;
                }


                this._drawStopwatch.Stop();
                var angleChangeValue = MathEx.ANGLE_360 * this._drawStopwatch.ElapsedMilliseconds / this._durationMilliseconds;
                if (this._rotateDirection)
                {
                    this._angle += angleChangeValue;
                }
                else
                {
                    this._angle -= angleChangeValue;
                }


                System.Drawing.Drawing2D.GraphicsPath graphicsPath = new System.Drawing.Drawing2D.GraphicsPath();
                foreach (EllipseInfo ellipseInfo in ellipseInfos)
                {
                    RectangleF reg = ellipseInfos.Rotate(ellipseInfo, this._angle);
                    graphics.FillEllipse(ellipseInfo.Fill, reg);
                    graphicsPath.AddEllipse(reg);
                }

                this.Refresh();

                if (this.Region != null)
                {
                    this.Region.Dispose();
                }

                this.Region = new System.Drawing.Region(graphicsPath);
                graphicsPath.Dispose();

                this._drawStopwatch.Restart();
            }
            catch (Exception ex)
            {
                ZLoger.Error(ex);
            }
        }




        /// <summary>
        /// 
        /// </summary>
        /// <param name="disposing"></param>
        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);

            try
            {
                this._timer.Stop();
                this._timer.Dispose();

                if (this._grafx != null)
                {
                    this._grafx.Dispose();
                    this._grafx = null;
                }

                if (this.Region != null)
                {
                    this.Region.Dispose();
                }

                if (this._ellipseInfos != null)
                {
                    this._ellipseInfos.ForEach(t => { t.Dispose(); });
                    this._ellipseInfos = null;
                }

                this._drawStopwatch.Stop();

                this._fillBrushes = null;
            }
            catch (Exception ex)
            {
                ZLoger.Error(ex);
            }
        }

       

        internal class EllipseInfoCollection : List<EllipseInfo>
        {
            /// <summary>
            /// 旋转路径圆半径
            /// </summary>
            private readonly float _rotatePathR;

            /// <summary>
            /// 动画圆半径
            /// </summary>
            private readonly float _animalR;

            private readonly PointF _rotateCenter;
            private readonly float _animalSize;

            public EllipseInfoCollection(PointF rotateCenter, float rotatePathR, float animalR, int capcity)
                : base(capcity)
            {
                this._rotateCenter = rotateCenter;
                this._animalR = animalR;
                this._rotatePathR = rotatePathR - animalR;
                this._animalSize = animalR * 2;
            }



            internal RectangleF Rotate(EllipseInfo ellipseInfo, double rotateAngle)
            {
                RectangleF rectangle;
                switch (ellipseInfo.Index)
                {
                    case 0:
                        rectangle = this.Rotate0(ellipseInfo, rotateAngle);
                        break;
                    case 1:
                        rectangle = this.Rotate1(ellipseInfo, rotateAngle);
                        break;
                    case 2:
                        rectangle = this.Rotate2(ellipseInfo, rotateAngle);
                        break;
                    case 3:
                        rectangle = this.Rotate3(ellipseInfo, rotateAngle);
                        break;
                    case 4:
                        rectangle = this.Rotate4(ellipseInfo, rotateAngle);
                        break;
                    case 5:
                        rectangle = this.Rotate5(ellipseInfo, rotateAngle);
                        break;
                    case 6:
                        rectangle = this.Rotate6(ellipseInfo, rotateAngle);
                        break;
                    case 7:
                        rectangle = this.Rotate7(ellipseInfo, rotateAngle);
                        break;
                    default:
                        throw new ArgumentOutOfRangeException($"圆个数太多了");
                }

                return rectangle;
            }



            /*******************************
            * 动画圆排列序号
            * |--------------------->X
            * |        2
            * |   1        3
            * |
            * |0               4
            * |
            * |   7        5
            * |        6
            * V
            * Y
            *******************************/

            private RectangleF Rotate0(EllipseInfo ellipseInfo, double rotateAngle)
            {
                double angleHude =MathEx.AngleToRadians(rotateAngle);
                float x, y;
                double tmpah;

                if (rotateAngle >= 0 && rotateAngle <= 90)
                {
                    x = this._rotateCenter.X - (float)(this._rotatePathR * Math.Cos(angleHude)) - this._animalR;
                    y = this._rotateCenter.Y - (float)(this._rotatePathR * Math.Sin(angleHude)) - this._animalR;
                }
                else if (rotateAngle > 90 && rotateAngle <= 180)
                {
                    tmpah = Math.PI - angleHude;
                    x = this._rotateCenter.X + (float)(this._rotatePathR * Math.Cos(tmpah)) - this._animalR;
                    y = this._rotateCenter.Y - (float)(this._rotatePathR * Math.Sin(tmpah)) - this._animalR;
                }
                else if (rotateAngle > 180 && rotateAngle <= 270)
                {
                    tmpah = angleHude - Math.PI;
                    x = this._rotateCenter.X + (float)(this._rotatePathR * Math.Cos(tmpah)) - this._animalR;
                    y = this._rotateCenter.Y + (float)(this._rotatePathR * Math.Sin(tmpah)) - this._animalR;
                }
                else
                {
                    tmpah = 2 * Math.PI - angleHude;
                    x = this._rotateCenter.X - (float)(this._rotatePathR * Math.Cos(tmpah)) - this._animalR;
                    y = this._rotateCenter.Y + (float)(this._rotatePathR * Math.Sin(tmpah)) - this._animalR;
                }

                return new RectangleF(x, y, this._animalSize, this._animalSize);
            }

            private RectangleF Rotate1(EllipseInfo ellipseInfo, double rotateAngle)
            {
                double angleHude =MathEx.AngleToRadians(rotateAngle + 45);
                float x, y;
                double tmpah;

                if (rotateAngle >= 0 && rotateAngle <= 45)
                {
                    x = this._rotateCenter.X - (float)(this._rotatePathR * Math.Cos(angleHude)) - this._animalR;
                    y = this._rotateCenter.Y - (float)(this._rotatePathR * Math.Sin(angleHude)) - this._animalR;
                }
                else if (rotateAngle > 45 && rotateAngle <= 135)
                {
                    tmpah = Math.PI - angleHude;
                    x = this._rotateCenter.X + (float)(this._rotatePathR * Math.Cos(tmpah)) - this._animalR;
                    y = this._rotateCenter.Y - (float)(this._rotatePathR * Math.Sin(tmpah)) - this._animalR;
                }
                else if (rotateAngle > 135 && rotateAngle <= 225)
                {
                    tmpah = angleHude - Math.PI;
                    x = this._rotateCenter.X + (float)(this._rotatePathR * Math.Cos(tmpah)) - this._animalR;
                    y = this._rotateCenter.Y + (float)(this._rotatePathR * Math.Sin(tmpah)) - this._animalR;
                }
                else
                {
                    tmpah = 2 * Math.PI - angleHude;
                    x = this._rotateCenter.X - (float)(this._rotatePathR * Math.Cos(tmpah)) - this._animalR;
                    y = this._rotateCenter.Y + (float)(this._rotatePathR * Math.Sin(tmpah)) - this._animalR;
                }

                return new RectangleF(x, y, this._animalSize, this._animalSize);
            }

            private RectangleF Rotate2(EllipseInfo ellipseInfo, double rotateAngle)
            {
                double angleHude =MathEx.AngleToRadians(rotateAngle + 90);
                float x, y;
                double tmpah;

                if (rotateAngle >= 0 && rotateAngle <= 90)
                {
                    tmpah = Math.PI - angleHude;
                    x = this._rotateCenter.X + (float)(this._rotatePathR * Math.Cos(tmpah)) - this._animalR;
                    y = this._rotateCenter.Y - (float)(this._rotatePathR * Math.Sin(tmpah)) - this._animalR;
                }
                else if (rotateAngle > 90 && rotateAngle <= 180)
                {
                    tmpah = angleHude - Math.PI;
                    x = this._rotateCenter.X + (float)(this._rotatePathR * Math.Cos(tmpah)) - this._animalR;
                    y = this._rotateCenter.Y + (float)(this._rotatePathR * Math.Sin(tmpah)) - this._animalR;
                }
                else if (rotateAngle > 180 && rotateAngle <= 270)
                {
                    tmpah = 2 * Math.PI - angleHude;
                    x = this._rotateCenter.X - (float)(this._rotatePathR * Math.Cos(tmpah)) - this._animalR;
                    y = this._rotateCenter.Y + (float)(this._rotatePathR * Math.Sin(tmpah)) - this._animalR;
                }
                else
                {
                    x = this._rotateCenter.X - (float)(this._rotatePathR * Math.Cos(angleHude)) - this._animalR;
                    y = this._rotateCenter.Y - (float)(this._rotatePathR * Math.Sin(angleHude)) - this._animalR;
                }

                return new RectangleF(x, y, this._animalSize, this._animalSize);
            }

            private RectangleF Rotate3(EllipseInfo ellipseInfo, double rotateAngle)
            {
                double angleHude =MathEx.AngleToRadians(rotateAngle + 135);
                float x, y;
                double tmpah;

                if (rotateAngle >= 0 && rotateAngle <= 45)
                {
                    tmpah = Math.PI - angleHude;
                    x = this._rotateCenter.X + (float)(this._rotatePathR * Math.Cos(tmpah)) - this._animalR;
                    y = this._rotateCenter.Y - (float)(this._rotatePathR * Math.Sin(tmpah)) - this._animalR;
                }
                else if (rotateAngle > 45 && rotateAngle <= 135)
                {
                    tmpah = angleHude - Math.PI;
                    x = this._rotateCenter.X + (float)(this._rotatePathR * Math.Cos(tmpah)) - this._animalR;
                    y = this._rotateCenter.Y + (float)(this._rotatePathR * Math.Sin(tmpah)) - this._animalR;
                }
                else if (rotateAngle > 135 && rotateAngle <= 225)
                {
                    tmpah = 2 * Math.PI - angleHude;
                    x = this._rotateCenter.X - (float)(this._rotatePathR * Math.Cos(tmpah)) - this._animalR;
                    y = this._rotateCenter.Y + (float)(this._rotatePathR * Math.Sin(tmpah)) - this._animalR;
                }
                else
                {
                    x = this._rotateCenter.X - (float)(this._rotatePathR * Math.Cos(angleHude)) - this._animalR;
                    y = this._rotateCenter.Y - (float)(this._rotatePathR * Math.Sin(angleHude)) - this._animalR;
                }

                return new RectangleF(x, y, this._animalSize, this._animalSize);
            }

            private RectangleF Rotate4(EllipseInfo ellipseInfo, double rotateAngle)
            {
                double angleHude =MathEx.AngleToRadians(rotateAngle + 180);
                float x, y;
                double tmpah;

                if (rotateAngle >= 0 && rotateAngle <= 90)
                {
                    tmpah = angleHude - Math.PI;
                    x = this._rotateCenter.X + (float)(this._rotatePathR * Math.Cos(tmpah)) - this._animalR;
                    y = this._rotateCenter.Y + (float)(this._rotatePathR * Math.Sin(tmpah)) - this._animalR;
                }
                else if (rotateAngle > 90 && rotateAngle <= 180)
                {
                    tmpah = 2 * Math.PI - angleHude;
                    x = this._rotateCenter.X - (float)(this._rotatePathR * Math.Cos(tmpah)) - this._animalR;
                    y = this._rotateCenter.Y + (float)(this._rotatePathR * Math.Sin(tmpah)) - this._animalR;
                }
                else if (rotateAngle > 180 && rotateAngle <= 270)
                {
                    x = this._rotateCenter.X - (float)(this._rotatePathR * Math.Cos(angleHude)) - this._animalR;
                    y = this._rotateCenter.Y - (float)(this._rotatePathR * Math.Sin(angleHude)) - this._animalR;
                }
                else
                {
                    tmpah = Math.PI - angleHude;
                    x = this._rotateCenter.X + (float)(this._rotatePathR * Math.Cos(tmpah)) - this._animalR;
                    y = this._rotateCenter.Y - (float)(this._rotatePathR * Math.Sin(tmpah)) - this._animalR;
                }

                return new RectangleF(x, y, this._animalSize, this._animalSize);
            }

            private RectangleF Rotate5(EllipseInfo ellipseInfo, double rotateAngle)
            {
                double angleHude =MathEx.AngleToRadians(rotateAngle + 225);
                float x, y;
                double tmpah;

                if (rotateAngle >= 0 && rotateAngle <= 45)
                {
                    tmpah = angleHude - Math.PI;
                    x = this._rotateCenter.X + (float)(this._rotatePathR * Math.Cos(tmpah)) - this._animalR;
                    y = this._rotateCenter.Y + (float)(this._rotatePathR * Math.Sin(tmpah)) - this._animalR;
                }
                else if (rotateAngle > 45 && rotateAngle <= 135)
                {
                    tmpah = 2 * Math.PI - angleHude;
                    x = this._rotateCenter.X - (float)(this._rotatePathR * Math.Cos(tmpah)) - this._animalR;
                    y = this._rotateCenter.Y + (float)(this._rotatePathR * Math.Sin(tmpah)) - this._animalR;
                }
                else if (rotateAngle > 135 && rotateAngle <= 225)
                {
                    x = this._rotateCenter.X - (float)(this._rotatePathR * Math.Cos(angleHude)) - this._animalR;
                    y = this._rotateCenter.Y - (float)(this._rotatePathR * Math.Sin(angleHude)) - this._animalR;
                }
                else
                {
                    tmpah = Math.PI - angleHude;
                    x = this._rotateCenter.X + (float)(this._rotatePathR * Math.Cos(tmpah)) - this._animalR;
                    y = this._rotateCenter.Y - (float)(this._rotatePathR * Math.Sin(tmpah)) - this._animalR;
                }

                return new RectangleF(x, y, this._animalSize, this._animalSize);
            }

            private RectangleF Rotate6(EllipseInfo ellipseInfo, double rotateAngle)
            {
                double angleHude =MathEx.AngleToRadians(rotateAngle + 270);
                float x, y;
                double tmpah;

                if (rotateAngle >= 0 && rotateAngle <= 90)
                {
                    tmpah = 2 * Math.PI - angleHude;
                    x = this._rotateCenter.X - (float)(this._rotatePathR * Math.Cos(tmpah)) - this._animalR;
                    y = this._rotateCenter.Y + (float)(this._rotatePathR * Math.Sin(tmpah)) - this._animalR;
                }
                else if (rotateAngle > 90 && rotateAngle <= 180)
                {
                    x = this._rotateCenter.X - (float)(this._rotatePathR * Math.Cos(angleHude)) - this._animalR;
                    y = this._rotateCenter.Y - (float)(this._rotatePathR * Math.Sin(angleHude)) - this._animalR;
                }
                else if (rotateAngle > 180 && rotateAngle <= 270)
                {
                    tmpah = Math.PI - angleHude;
                    x = this._rotateCenter.X + (float)(this._rotatePathR * Math.Cos(tmpah)) - this._animalR;
                    y = this._rotateCenter.Y - (float)(this._rotatePathR * Math.Sin(tmpah)) - this._animalR;
                }
                else
                {
                    tmpah = angleHude - Math.PI;
                    x = this._rotateCenter.X + (float)(this._rotatePathR * Math.Cos(tmpah)) - this._animalR;
                    y = this._rotateCenter.Y + (float)(this._rotatePathR * Math.Sin(tmpah)) - this._animalR;
                }

                return new RectangleF(x, y, this._animalSize, this._animalSize);
            }

            private RectangleF Rotate7(EllipseInfo ellipseInfo, double rotateAngle)
            {
                double angleHude =MathEx.AngleToRadians(rotateAngle + 315);
                float x, y;
                double tmpah;

                if (rotateAngle >= 0 && rotateAngle <= 45 ||
                    rotateAngle >= 315)
                {
                    tmpah = 2 * Math.PI - angleHude;
                    x = this._rotateCenter.X - (float)(this._rotatePathR * Math.Cos(tmpah)) - this._animalR;
                    y = this._rotateCenter.Y + (float)(this._rotatePathR * Math.Sin(tmpah)) - this._animalR;
                }
                else if (rotateAngle > 45 && rotateAngle <= 135)
                {
                    x = this._rotateCenter.X - (float)(this._rotatePathR * Math.Cos(angleHude)) - this._animalR;
                    y = this._rotateCenter.Y - (float)(this._rotatePathR * Math.Sin(angleHude)) - this._animalR;
                }
                else if (rotateAngle > 135 && rotateAngle <= 225)
                {
                    tmpah = Math.PI - angleHude;
                    x = this._rotateCenter.X + (float)(this._rotatePathR * Math.Cos(tmpah)) - this._animalR;
                    y = this._rotateCenter.Y - (float)(this._rotatePathR * Math.Sin(tmpah)) - this._animalR;
                }
                else
                {
                    tmpah = angleHude - Math.PI;
                    x = this._rotateCenter.X + (float)(this._rotatePathR * Math.Cos(tmpah)) - this._animalR;
                    y = this._rotateCenter.Y + (float)(this._rotatePathR * Math.Sin(tmpah)) - this._animalR;
                }

                return new RectangleF(x, y, this._animalSize, this._animalSize);
            }
        }

        internal class EllipseInfo : IDisposable
        {
            public Brush Fill { get; private set; }

            public PointF Center { get; private set; }

            public int Index { get; private set; }

            public EllipseInfo(PointF center, Brush fill, int index)
            {
                this.Center = center;
                this.Fill = fill;
                this.Index = index;
            }

            public void Dispose()
            {
                this.Fill = null;
            }
        }
    }
}
